package org.example.ding.controller;

import org.example.ding.dto.DishDto;
import org.example.ding.entity.Dish;
import org.example.ding.entity.DishCategory;
import org.example.ding.entity.OrderRecord;
import org.example.ding.service.CustomUserDetailsService;
import org.example.ding.service.DishService;
import org.example.ding.service.DishCategoryService;
import org.example.ding.service.NutritionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 点餐控制器
 */
@Controller
@RequestMapping("/meals")
public class OrderController {

    @Autowired
    private DishService dishService;

    @Autowired
    private DishCategoryService dishCategoryService;

    @Autowired
    private NutritionService nutritionService;

    /**
     * 点餐主页面
     */
    @GetMapping
    public String mealsHome(@AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
                           @RequestParam(required = false) Long categoryId,
                           @RequestParam(required = false) String keyword,
                           @RequestParam(defaultValue = "0") int page,
                           @RequestParam(defaultValue = "12") int size,
                           Model model) {

        try {
            System.out.println("访问点餐页面，用户: " + (principal != null ? principal.getUsername() : "未登录"));

            if (principal == null) {
                return "redirect:/login";
            }

            Long userId = principal.getId();

            // 安全地获取数据
            try {
                List<DishCategory> categories = dishCategoryService.getAllCategories();
                model.addAttribute("categories", categories);
                System.out.println("获取到 " + categories.size() + " 个分类");
            } catch (Exception e) {
                System.err.println("获取分类失败: " + e.getMessage());
                model.addAttribute("categories", new ArrayList<>());
            }

            try {
                Pageable pageable = PageRequest.of(page, size, Sort.by("popularityScore").descending());
                Page<Dish> dishPage = dishService.getDishes(pageable);
                model.addAttribute("dishPage", dishPage);
                System.out.println("获取到 " + dishPage.getTotalElements() + " 个菜品");
            } catch (Exception e) {
                System.err.println("获取菜品失败: " + e.getMessage());
                model.addAttribute("dishPage", Page.empty());
            }

            model.addAttribute("currentCategoryId", categoryId);
            model.addAttribute("currentKeyword", keyword);
            model.addAttribute("user", principal);

            return "meals/index-simple";

        } catch (Exception e) {
            System.err.println("点餐页面加载失败: " + e.getMessage());
            e.printStackTrace();
            return "error";
        }
    }

    /**
     * 早餐页面
     */
    @GetMapping("/breakfast")
    public String breakfast(@AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
                           @RequestParam(defaultValue = "0") int page,
                           @RequestParam(defaultValue = "12") int size,
                           Model model) {
        
        return getMealPage(principal, DishCategory.MealType.BREAKFAST, page, size, model, "meals/breakfast");
    }

    /**
     * 午餐页面
     */
    @GetMapping("/lunch")
    public String lunch(@AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
                       @RequestParam(defaultValue = "0") int page,
                       @RequestParam(defaultValue = "12") int size,
                       Model model) {
        
        return getMealPage(principal, DishCategory.MealType.LUNCH, page, size, model, "meals/lunch");
    }

    /**
     * 晚餐页面
     */
    @GetMapping("/dinner")
    public String dinner(@AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
                        @RequestParam(defaultValue = "0") int page,
                        @RequestParam(defaultValue = "12") int size,
                        Model model) {
        
        return getMealPage(principal, DishCategory.MealType.DINNER, page, size, model, "meals/dinner");
    }

    /**
     * 小食页面
     */
    @GetMapping("/snacks")
    public String snacks(@AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
                        @RequestParam(defaultValue = "0") int page,
                        @RequestParam(defaultValue = "12") int size,
                        Model model) {
        
        return getMealPage(principal, DishCategory.MealType.SNACK, page, size, model, "meals/snacks");
    }

    /**
     * 通用餐别页面处理方法
     */
    private String getMealPage(CustomUserDetailsService.CustomUserPrincipal principal,
                              DishCategory.MealType mealType,
                              int page, int size, Model model, String viewName) {
        
        Long userId = principal.getId();
        
        // 获取该餐别的分类
        List<DishCategory> categories = dishCategoryService.getCategoriesByMealType(mealType);
        
        // 获取该餐别的菜品
        List<Dish> allDishes = new java.util.ArrayList<>();
        for (DishCategory category : categories) {
            allDishes.addAll(dishService.getDishesByCategory(category.getId()));
        }
        
        // 手动分页
        int start = page * size;
        int end = Math.min(start + size, allDishes.size());
        List<Dish> pagedDishes = allDishes.subList(start, end);
        
        List<DishDto> dishDtos = pagedDishes.stream()
            .map(DishDto::fromDish)
            .collect(Collectors.toList());
        
        // 获取今日该餐别的点餐记录
        List<OrderRecord> todayMealOrders = nutritionService.getTodayOrders(userId).stream()
            .filter(order -> {
                OrderRecord.MealType orderMealType = order.getMealType();
                return (mealType == DishCategory.MealType.BREAKFAST && orderMealType == OrderRecord.MealType.BREAKFAST) ||
                       (mealType == DishCategory.MealType.LUNCH && orderMealType == OrderRecord.MealType.LUNCH) ||
                       (mealType == DishCategory.MealType.DINNER && orderMealType == OrderRecord.MealType.DINNER) ||
                       (mealType == DishCategory.MealType.SNACK && orderMealType == OrderRecord.MealType.SNACK);
            })
            .collect(Collectors.toList());
        
        model.addAttribute("categories", categories);
        model.addAttribute("dishes", dishDtos);
        model.addAttribute("todayOrders", todayMealOrders);
        model.addAttribute("mealType", mealType);
        model.addAttribute("currentPage", page);
        model.addAttribute("totalPages", (allDishes.size() + size - 1) / size);
        model.addAttribute("hasNext", end < allDishes.size());
        model.addAttribute("hasPrevious", page > 0);
        
        return viewName;
    }

    /**
     * 菜品详情页面
     */
    @GetMapping("/dish/{dishId}")
    public String dishDetail(@PathVariable Long dishId, Model model) {
        Dish dish = dishService.findAvailableById(dishId)
            .orElseThrow(() -> new RuntimeException("菜品不存在或不可用"));
        
        DishDto dishDto = DishDto.fromDish(dish);
        
        // 获取相关菜品（同分类的其他菜品）
        List<Dish> relatedDishes = dishService.getDishesByCategory(dish.getCategory().getId())
            .stream()
            .filter(d -> !d.getId().equals(dishId))
            .limit(4)
            .collect(Collectors.toList());
        
        List<DishDto> relatedDishDtos = relatedDishes.stream()
            .map(DishDto::fromDish)
            .collect(Collectors.toList());
        
        model.addAttribute("dish", dishDto);
        model.addAttribute("relatedDishes", relatedDishDtos);
        
        return "meals/dish-detail";
    }

    /**
     * 搜索菜品 (AJAX)
     */
    @GetMapping("/api/search")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> searchDishes(
            @RequestParam(required = false) Long categoryId,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) String spiceLevel,
            @RequestParam(required = false) String cookingMethod,
            @RequestParam(required = false) BigDecimal minCalories,
            @RequestParam(required = false) BigDecimal maxCalories,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "12") int size) {
        
        Dish.SpiceLevel spiceLevelEnum = null;
        if (spiceLevel != null && !spiceLevel.isEmpty()) {
            spiceLevelEnum = Dish.SpiceLevel.valueOf(spiceLevel);
        }
        
        Dish.CookingMethod cookingMethodEnum = null;
        if (cookingMethod != null && !cookingMethod.isEmpty()) {
            cookingMethodEnum = Dish.CookingMethod.valueOf(cookingMethod);
        }
        
        Pageable pageable = PageRequest.of(page, size, Sort.by("popularityScore").descending());
        Page<Dish> dishPage = dishService.searchDishes(categoryId, keyword, spiceLevelEnum, 
                                                      cookingMethodEnum, minCalories, maxCalories, pageable);
        
        Page<DishDto> dishDtoPage = dishPage.map(DishDto::fromDish);
        
        Map<String, Object> response = new HashMap<>();
        response.put("dishes", dishDtoPage.getContent());
        response.put("totalPages", dishDtoPage.getTotalPages());
        response.put("totalElements", dishDtoPage.getTotalElements());
        response.put("currentPage", page);
        response.put("hasNext", dishDtoPage.hasNext());
        response.put("hasPrevious", dishDtoPage.hasPrevious());
        
        return ResponseEntity.ok(response);
    }

    /**
     * 获取菜品详情 (AJAX)
     */
    @GetMapping("/api/dish/{dishId}")
    @ResponseBody
    public ResponseEntity<DishDto> getDishDetail(@PathVariable Long dishId) {
        Dish dish = dishService.findAvailableById(dishId)
            .orElseThrow(() -> new RuntimeException("菜品不存在或不可用"));
        
        DishDto dishDto = DishDto.fromDish(dish);
        return ResponseEntity.ok(dishDto);
    }

    /**
     * 获取热门菜品 (AJAX)
     */
    @GetMapping("/api/popular")
    @ResponseBody
    public ResponseEntity<List<DishDto>> getPopularDishes(@RequestParam(defaultValue = "10") int limit) {
        List<Dish> dishes = dishService.getPopularDishes(limit);
        List<DishDto> dishDtos = dishes.stream()
            .map(DishDto::fromDish)
            .collect(Collectors.toList());
        
        return ResponseEntity.ok(dishDtos);
    }

    /**
     * 根据分类获取菜品 (AJAX)
     */
    @GetMapping("/api/category/{categoryId}")
    @ResponseBody
    public ResponseEntity<List<DishDto>> getDishesByCategory(@PathVariable Long categoryId) {
        List<Dish> dishes = dishService.getDishesByCategory(categoryId);
        List<DishDto> dishDtos = dishes.stream()
            .map(DishDto::fromDish)
            .collect(Collectors.toList());
        
        return ResponseEntity.ok(dishDtos);
    }

    /**
     * 单个菜品点餐 (AJAX)
     */
    @PostMapping("/api/order")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> orderDish(
            @AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
            @RequestParam Long dishId,
            @RequestParam String mealType,
            @RequestParam(defaultValue = "1.0") BigDecimal portionSize) {

        Map<String, Object> response = new HashMap<>();

        try {
            Long userId = principal.getId();
            OrderRecord.MealType mealTypeEnum = OrderRecord.MealType.valueOf(mealType);

            OrderRecord orderRecord = nutritionService.recordOrder(userId, dishId, mealTypeEnum, portionSize);

            response.put("success", true);
            response.put("message", "点餐成功！");
            // 只返回简单信息，避免循环引用
            response.put("orderId", orderRecord.getId());

        } catch (RuntimeException e) {
            response.put("success", false);
            response.put("message", e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 批量点餐 (购物车提交)
     */
    @PostMapping("/api/orders/batch")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> submitCart(
            @AuthenticationPrincipal CustomUserDetailsService.CustomUserPrincipal principal,
            @RequestBody List<CartItem> cartItems) {

        Map<String, Object> response = new HashMap<>();

        try {
            System.out.println("收到批量订单请求，购物车项目数量: " + cartItems.size()); // 调试日志
            for (int i = 0; i < cartItems.size(); i++) {
                CartItem item = cartItems.get(i);
                System.out.println("项目 " + i + ": dishId=" + item.getDishId() +
                                 ", dishName=" + item.getDishName() +
                                 ", mealType=" + item.getMealType() +
                                 ", portionSize=" + item.getPortionSize()); // 调试日志
            }

            Long userId = principal.getId();

            // 转换为OrderRequest
            List<NutritionService.OrderRequest> orderRequests = cartItems.stream()
                .map(item -> new NutritionService.OrderRequest(
                    item.getDishId(),
                    item.getMealType().toString(),
                    BigDecimal.valueOf(item.getPortionSize())))
                .collect(Collectors.toList());

            List<OrderRecord> orderRecords = nutritionService.recordOrders(userId, orderRequests);

            response.put("success", true);
            response.put("message", "订单提交成功！共点餐 " + orderRecords.size() + " 个菜品");
            // 只返回简单的订单信息，避免循环引用导致JSON序列化错误
            response.put("orderCount", orderRecords.size());

        } catch (RuntimeException e) {
            response.put("success", false);
            response.put("message", e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 购物车项目内部类
     */
    public static class CartItem {
        private Long dishId;
        private String dishName;
        private OrderRecord.MealType mealType;
        private Double portionSize;
        private Double price;

        public CartItem() {}

        public CartItem(Long dishId, String dishName, OrderRecord.MealType mealType,
                       Double portionSize, Double price) {
            this.dishId = dishId;
            this.dishName = dishName;
            this.mealType = mealType;
            this.portionSize = portionSize;
            this.price = price;
        }

        // Getters and Setters
        public Long getDishId() { return dishId; }
        public void setDishId(Long dishId) { this.dishId = dishId; }
        public String getDishName() { return dishName; }
        public void setDishName(String dishName) { this.dishName = dishName; }
        public OrderRecord.MealType getMealType() { return mealType; }

        // 统一的setMealType方法，支持字符串和枚举
        public void setMealType(Object mealTypeObj) {
            if (mealTypeObj == null) {
                this.mealType = null;
                return;
            }

            if (mealTypeObj instanceof OrderRecord.MealType) {
                this.mealType = (OrderRecord.MealType) mealTypeObj;
            } else if (mealTypeObj instanceof String) {
                String mealTypeStr = (String) mealTypeObj;
                if (!mealTypeStr.trim().isEmpty()) {
                    try {
                        this.mealType = OrderRecord.MealType.valueOf(mealTypeStr.toUpperCase());
                    } catch (IllegalArgumentException e) {
                        throw new RuntimeException("无效的餐别类型: " + mealTypeStr);
                    }
                }
            } else {
                throw new RuntimeException("不支持的餐别类型: " + mealTypeObj.getClass().getSimpleName());
            }
        }

        public Double getPortionSize() { return portionSize; }
        public void setPortionSize(Double portionSize) { this.portionSize = portionSize; }
        public Double getPrice() { return price; }
        public void setPrice(Double price) { this.price = price; }
    }
}
